package com.blitscreen.events 
{
	import flash.events.Event;
	import flash.utils.getQualifiedClassName;
	
	import com.blitscreen.log.BlitDebug;
	import com.bourre.collection.Collection;
	import com.bourre.collection.Iterator;
	import com.bourre.collection.WeakCollection;
	import com.bourre.error.IllegalArgumentException;
	import com.bourre.error.UnsupportedOperationException;
	import com.bourre.events.DynBasicEvent;
	import com.bourre.log.PixlibStringifier;		

	/**
	 * @author Cedric Nehemie
	 */
	public class FastEventBroadcaster 
	{
		private static var _oI : FastEventBroadcaster = null;

		private var _oTarget : Object;
		private var _mAll : Collection;
		private var _cType : Class;
		
		public function FastEventBroadcaster( target : Object = null, type : Class = null )
		{
			_oTarget = ( target == null ) ? this : target;

			_mAll = new WeakCollection();
			setListenerType( type );
		}

		public static function getInstance() : FastEventBroadcaster
		{
			if ( !(FastEventBroadcaster._oI is FastEventBroadcaster) ) FastEventBroadcaster._oI = new FastEventBroadcaster();
			return FastEventBroadcaster._oI;
		}

		public function setListenerType( type : Class ) : void
		{
			var i : Iterator = _mAll.iterator();
			while ( i.hasNext() )
			{
				if ( !(i.next() is type) )
				{
					var msg : String = this + ".setListenerType( " + type
					+ " ) failed, your listener must be '" + _cType + "' typed";

					BlitDebug.ERROR( msg );
					throw( new IllegalArgumentException( msg ) );
				}
			}

			_cType = type;
		}

		public function getListenerCollection() : Collection
		{
			return _mAll;
		}
		
		public function isRegistered( listener : Object ) : Boolean
		{
			return _mAll.contains( listener );
		}

		public function addListener( listener : Object ) : Boolean
		{
			if ( _cType != null && !( listener is _cType ) )
			{
				var msg : String = this + ".addListener( " + listener
				+ " ) failed, your listener must be '" + _cType + "' typed";
			
				BlitDebug.ERROR( msg );
				throw( new IllegalArgumentException( msg ) );
			} 
			else
			{
				return _mAll.add( listener );
			}
		}

		public function removeListener( listener : Object ) : Boolean
		{
			var b : Boolean = _mAll.contains( listener );
			_mAll.remove( listener );
			return b;
		}
		
		public function removeAllListeners() : void
		{
			_mAll.clear();
		}

		public function isEmpty() : Boolean
		{
			return _mAll.isEmpty();
		}

		public function dispatchEvent( o : Object ) : void
		{
			var e : DynBasicEvent = new DynBasicEvent( o["type"] );
			for ( var p : String in o ) if (p != "type") e[p] = o[p];
			broadcastEvent( e );
		}

		public function broadcastEvent( e : Event ) : void
		{
			if ( !(_mAll.isEmpty()) ) _broadcastEvent( e );
		}

		public function _broadcastEvent( e : Event ) : void
		{
			var type : String = e.type;
			var a : Array = _mAll.toArray();
			var l : Number = a.length;

			while ( --l -( -1) ) a[l][type](e);
		}

		/**
		 * Returns the string representation of this instance.
		 * @return the string representation of this instance
		 */
		public function toString() : String 
		{
			return PixlibStringifier.stringify( this );
		}

	}
}
